﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Adams.Admin.Business.Events
{
    public static class CreateEvent
    {
        public static Adams.Admin.DataTransfer.Events.CreateEvent.PageLoad PageLoad(int occuranceId)
        {
            return DataAccess.Events.CreateEvent.PageLoad(occuranceId);
        }

        public static DataTransfer.FormOutput SaveEvent(DataTransfer.Events.CreateEvent.FormInput input)
        {
            var output = Validation.PerformBasicValidation(input);

            if (output.IsValid)
            {
                if (!input.IsAllDay)
                {
                    if (Shared.Validation.Empty(input.StartDateTime))
                    {
                        output.InvalidFields.Add(new DataTransfer.InvalidField()
                        {
                            Name = "StartDateTime",
                            Code = 1
                        });
                    }

                    if (Shared.Validation.Empty(input.EndDateTime))
                    {
                        output.InvalidFields.Add(new DataTransfer.InvalidField()
                        {
                            Name = "EndDateTime",
                            Code = 1
                        });
                    }
                }

                if (output.IsValid)
                {
                    if (!input.IsAllDay)
                    {
                        input.StartDate = Shared.DateHelper.CombineDateTime(input.StartDate, input.StartDateTime).ToString();
                        input.EndDate = Shared.DateHelper.CombineDateTime(input.EndDate, input.EndDateTime).ToString();
                    }

                    var save = new Adams.Admin.DataTransfer.Events.CreateEvent.SaveEvent();

                    save.Event = new Shared.Entities.Events.Event()
                    {
                        ID = input.OccuranceID,
                        Title = input.Title,
                        ShortDescription = input.ShortDescription,
                        Location = input.Location,
                        Description = input.Description,
                        StartDate = input.StartDate.ToDateTime(),
                        EndDate = input.EndDate.ToDateTime(),
                        TimeZone = input.TimeZone.ToInt(),
                        IsAllDay = input.IsAllDay,
                        IsRepeat = input.IsRepeat,
                        RepeatType = input.RepeatType.ToInt(),
                        RepeatEndType = input.RepeatEndType.ToInt(),
                        RepeatEndOccurences = input.RepeatEndOccurences.ToInt(),
                        RepeatEndDate = input.RepeatEndDate.ToDateTime(),
                        RepeatEvery = input.RepeatEvery.ToInt(),
                        RepeatStartsOn = input.RepeatStartsOn.ToDateTime(),
                        RepeatWeeklySun = input.RepeatWeeklySun.ToBool(),
                        RepeatWeeklyMon = input.RepeatWeeklyMon.ToBool(),
                        RepeatWeeklyTeu = input.RepeatWeeklyTeu.ToBool(),
                        RepeatWeeklyWed = input.RepeatWeeklyWed.ToBool(),
                        RepeatWeeklyThu = input.RepeatWeeklyThu.ToBool(),
                        RepeatWeeklyFri = input.RepeatWeeklyFri.ToBool(),
                        RepeatWeeklySat = input.RepeatWeeklySat.ToBool(),
                        RepeatMonthlyBy = input.RepeatMonthlyBy.ToInt(),
                        Calendar = new Shared.Entities.Events.Calendar()
                        {
                            ID = input.CalendarID.ToInt()
                        }
                    };
                    save.Event.Occurances = GenerateOccurances(save.Event);

                    DataAccess.Events.CreateEvent.Save(save, input.EditRepeatType.ToInt());
                    output.IsSaved = true;
                }
                
            }

            return output;
        }

        public static void DeleteEvent(DataTransfer.Events.CreateEvent.DeleteInput input)
        {
            DataAccess.Events.CreateEvent.Delete(input);
        }

        public static Shared.Entities.Events.OccuranceCollection GenerateOccurances(Shared.Entities.Events.Event oEvent)
        {
            var occurances = new Shared.Entities.Events.OccuranceCollection();      
            
            if (oEvent.IsRepeat)
            {
                int count = 0;
                double durationmins = Shared.DateHelper.DiffMins(oEvent.StartDate, oEvent.EndDate);
                DateTime begin = oEvent.RepeatStartsOn;
                DateTime current = begin;
                DateTime end = DateTime.UtcNow;

                if (!oEvent.IsAllDay)
                {
                    begin = Shared.DateHelper.CombineDateTime(begin.ToShortDateString(), oEvent.StartDate.ToShortTimeString());
                    current = Shared.DateHelper.CombineDateTime(current.ToShortDateString(), oEvent.StartDate.ToShortTimeString());
                    end = Shared.DateHelper.CombineDateTime(end.ToShortDateString(), oEvent.EndDate.ToShortTimeString());
                }

                if (oEvent.RepeatEndType == 1)
                {
                    end = DateTime.UtcNow.AddYears(5);
                }
                else if (oEvent.RepeatEndType == 2)
                {
                    end = DateTime.UtcNow.AddYears(5);
                }
                else if (oEvent.RepeatEndType == 3)
                {
                    end = oEvent.RepeatEndDate;
                }

                // Generate multipe occurances
                if (oEvent.RepeatType == 1)
                {
                    #region Daily
                    // Daily
                    while ((oEvent.RepeatEndType != 2 && current <= end) 
                        || (oEvent.RepeatEndType == 2 && count < oEvent.RepeatEndOccurences))
                    {
                        var occurance = new Shared.Entities.Events.Occurance()
                        {
                            Event = new Shared.Entities.Events.Event()
                            {
                                ID = oEvent.ID
                            },
                            Title = oEvent.Title,
                            ShortDescription = oEvent.ShortDescription,
                            Description = oEvent.Description,
                            Location = oEvent.Location,
                            StartDate = current,
                            EndDate = current.AddMinutes(durationmins),
                            TimeZone = oEvent.TimeZone,
                            IsAllDay = oEvent.IsAllDay
                        };
                        occurances.Add(occurance);

                        count++;
                        current = current.AddDays(oEvent.RepeatEvery);
                    }
                    #endregion
                }
                else if (oEvent.RepeatType == 2)
                {
                    #region Weekly
                    // Weekly
                    while ((oEvent.RepeatEndType != 2 && current <= end)
                        || (oEvent.RepeatEndType == 2 && count < oEvent.RepeatEndOccurences))
                    {
                        if (oEvent.RepeatWeeklySun && current.DayOfWeek == DayOfWeek.Sunday ||
                           oEvent.RepeatWeeklyMon && current.DayOfWeek == DayOfWeek.Monday ||
                           oEvent.RepeatWeeklyTeu && current.DayOfWeek == DayOfWeek.Tuesday ||
                           oEvent.RepeatWeeklyWed && current.DayOfWeek == DayOfWeek.Wednesday ||
                           oEvent.RepeatWeeklyThu && current.DayOfWeek == DayOfWeek.Thursday ||
                           oEvent.RepeatWeeklyFri && current.DayOfWeek == DayOfWeek.Friday ||
                           oEvent.RepeatWeeklySat && current.DayOfWeek == DayOfWeek.Saturday)
                        {
                            var occurance = new Shared.Entities.Events.Occurance()
                            {
                                Event = new Shared.Entities.Events.Event()
                                {
                                    ID = oEvent.ID
                                },
                                Title = oEvent.Title,
                                ShortDescription = oEvent.ShortDescription,
                                Description = oEvent.Description,
                                Location = oEvent.Location,
                                StartDate = current,
                                EndDate = current.AddMinutes(durationmins),
                                TimeZone = oEvent.TimeZone,
                                IsAllDay = oEvent.IsAllDay
                            };
                            occurances.Add(occurance);
                            count++;
                        }

                        if (current.DayOfWeek == DayOfWeek.Saturday)
                        {
                            current = current.AddDays(1);
                            current = current.AddDays((oEvent.RepeatEvery - 1) * 7);
                        }
                        else
                        {
                            current = current.AddDays(1);
                        }
                    }
                    #endregion
                } 
                else if (oEvent.RepeatType == 3)
                {
                    #region Monthly
                    // Monthly
                    while ((oEvent.RepeatEndType != 2 && current <= end)
                        || (oEvent.RepeatEndType == 2 && count < oEvent.RepeatEndOccurences))
                    {

                        var occurance = new Shared.Entities.Events.Occurance()
                        {
                            Event = new Shared.Entities.Events.Event()
                            {
                                ID = oEvent.ID
                            },
                            Title = oEvent.Title,
                            ShortDescription = oEvent.ShortDescription,
                            Description = oEvent.Description,
                            Location = oEvent.Location,
                            StartDate = current,
                            EndDate = current.AddMinutes(durationmins),
                            TimeZone = oEvent.TimeZone,
                            IsAllDay = oEvent.IsAllDay
                        };
                        occurances.Add(occurance);
                        count++;

                        if (oEvent.RepeatMonthlyBy == 1)
                        {
                            current = current.AddMonths(1);
                        }
                        else if (oEvent.RepeatMonthlyBy == 2)
                        {
                            current = current.AddMonths(1);
                            int weekindex = Shared.DateHelper.GetDayOccurance(begin);
                            int occur = 0;
                            int oneweekbefore = 0;
                            bool found = false;
                            for (int i = 1; i <= DateTime.DaysInMonth(current.Year, current.Month); i++)
                            {
                                DateTime d = new DateTime(current.Year, current.Month, i);
                                if (d.DayOfWeek == begin.DayOfWeek)
                                {
                                    occur++;
                                }
                                if (occur == (weekindex - 1))
                                {
                                    oneweekbefore = i;
                                }
                                if (occur == weekindex)
                                {
                                    current.AddDays(i - current.Day);
                                    found = true;
                                    break;
                                }
                            }
                            if (!found)
                            {
                                current.AddDays(oneweekbefore - current.Day);
                            }
                        }
                    }
                    #endregion
                } 
                else if (oEvent.RepeatType == 4)
                {
                    #region Yearly
                    // Yearly
                    while ((oEvent.RepeatEndType != 2 && current <= end)
                        || (oEvent.RepeatEndType == 2 && count < oEvent.RepeatEndOccurences))
                    {
                        var occurance = new Shared.Entities.Events.Occurance()
                        {
                            Event = new Shared.Entities.Events.Event()
                            {
                                ID = oEvent.ID
                            },
                            Title = oEvent.Title,
                            ShortDescription = oEvent.ShortDescription,
                            Description = oEvent.Description,
                            Location = oEvent.Location,
                            StartDate = current,
                            EndDate = current.AddMinutes(durationmins),
                            TimeZone = oEvent.TimeZone,
                            IsAllDay = oEvent.IsAllDay
                        };
                        occurances.Add(occurance);

                        count++;
                        current = current.AddYears(oEvent.RepeatEvery);
                    }
                    #endregion
                }
            }
            else
            {
                // Only generate one occurance
                var occurance = new Shared.Entities.Events.Occurance() { 
	                Event = new Shared.Entities.Events.Event() {
                        ID = oEvent.ID
                    },
	                Title = oEvent.Title,
	                ShortDescription = oEvent.ShortDescription,
	                Description = oEvent.Description,
	                Location = oEvent.Location,
	                StartDate = oEvent.StartDate,
                    EndDate = oEvent.EndDate,
	                TimeZone = oEvent.TimeZone,
                    IsAllDay = oEvent.IsAllDay
                };
                occurances.Add(occurance);
            }

            return occurances;
        }
    }
}
